package com.woyao;

import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.speech.RecognitionListener;
import android.speech.SpeechRecognizer;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import com.woyao.core.util.Common;

import org.json.JSONObject;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;


public class VoiceActivity extends AppCompatActivity implements RecognitionListener {
    private static final String serverURL = "http://vop.baidu.com/server_api";
    private static String token = "";
    private static final String apiKey = "6QhPko9rFNtwpKGgDO42yT7t";
    private static final String secretKey = "SwVg0shBD4ZQ97YoZCV0NxW8GevuuaY2";
    private static final String cuid = "9562650";

    // 以文件的形式保存
    private String testFileName = "recording.pcm";
    private File recordingFile;
    private TextView voice_result;

    Button startBtn;
    Button stopBtn;
    Button playBtn;
    Button recognizeBtn;
    Button matchBtn;

    Boolean isRecording = false;

    int audioSource=MediaRecorder.AudioSource.MIC ;
    int frequency = 8000;

    int channelConfiguration =  AudioFormat.CHANNEL_IN_MONO;
    int audioEncoding = AudioFormat.ENCODING_PCM_16BIT ;

    RecordAudio recordTask;
    PlayAudio playTask;

    private MediaRecorder myRecorder;
    private MediaPlayer myPlayer;

    private SpeechRecognizer speechRecognizer;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_voice);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        final ActionBar ab = getSupportActionBar();
        ab.setDisplayShowHomeEnabled(true); // show or hide the default home button
        ab.setDisplayHomeAsUpEnabled(true);
        ab.setDisplayShowCustomEnabled(true); // enable overriding the default toolbar layout

        this.setTitle("说明您的合作需求");

        String filepathstr = Environment.getExternalStorageDirectory().getAbsolutePath()+"/voice/";
        File fpath = new File(filepathstr);
        fpath.mkdirs();//创建文件夹
        try {
            recordingFile = File.createTempFile("recording", ".pcm", fpath);
            testFileName =  recordingFile.getPath();
        } catch (IOException e) {
            e.printStackTrace();
        }

        myPlayer = new MediaPlayer();
        myRecorder = new MediaRecorder();

        startBtn = (Button ) findViewById(R.id.start);
        startBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
//                startASR();
                startRecord();
//                startMediaRecord();
            }
        });

        stopBtn = (Button ) findViewById(R.id.stop);
        stopBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                isRecording = false;
//                myRecorder.stop();
//                voice_result.setText("停止录音");
            }
        });

        playBtn = (Button ) findViewById(R.id.play);
        playBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                voice_result.setText("开始播放");
                playRecord();
            }
        });

        recognizeBtn = (Button ) findViewById(R.id.recognize);
        recognizeBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                recognizeRecord();
            }
        });

        matchBtn = (Button ) findViewById(R.id.match);
        matchBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Common.setProfileAttr("firstvoicetext", voice_result.getText().toString());
                Intent intent = new Intent();
                intent.putExtra("from", "register");
                intent.setClass(VoiceActivity.this, ChanceActivity.class);
                startActivity(intent);
            }
        });

        voice_result = (TextView) findViewById(R.id.id_voicetext);

//        speechRecognizer = SpeechRecognizer.createSpeechRecognizer(this, new ComponentName(this, VoiceRecognitionService.class));
//        // 注册监听器
//        speechRecognizer.setRecognitionListener(this);
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if(requestCode==1&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
            startBtn.setEnabled(false);
            stopBtn.setEnabled(true);

            playBtn.setEnabled(false);

            recordTask = new RecordAudio();
            recordTask.execute();
        }else {
            Toast.makeText(this,"用户拒绝了权限",Toast.LENGTH_SHORT).show();
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    void startMediaRecord() {
        if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.RECORD_AUDIO)
                != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this,new String[]{
                    android.Manifest.permission.RECORD_AUDIO},1);
        }else {

            startBtn.setEnabled(false);
            stopBtn.setEnabled(true);

            playBtn.setEnabled(false);

            try {
                myRecorder = new MediaRecorder();
                // 从麦克风源进行录音
                myRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
                // 设置输出格式
                myRecorder.setOutputFormat(MediaRecorder.OutputFormat.AMR_NB);
                // 设置编码格式
                myRecorder.setAudioChannels(1);
                myRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                myRecorder.setAudioEncodingBitRate( 16 );
                myRecorder.setAudioSamplingRate(frequency);
                myRecorder.setOutputFile(testFileName);
                myRecorder.prepare();
                myRecorder.start();
                voice_result.setText("开始录音");
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }



    void startRecord() {
        if(ContextCompat.checkSelfPermission(this, android.Manifest.permission.RECORD_AUDIO)
                != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this,new String[]{
                    android.Manifest.permission.RECORD_AUDIO},1);
        }else {
            startBtn.setEnabled(false);
            stopBtn.setEnabled(true);

            playBtn.setEnabled(false);


            recordTask = new RecordAudio();
            recordTask.execute();
        }



    }




    void playRecord() {
        Log.i("haiming","播放");

        playTask = new PlayAudio();
        playTask.execute();

//        try {
//            myPlayer.reset();
//            myPlayer.setDataSource(testFileName);
//            if (!myPlayer.isPlaying()) {
//                myPlayer.prepare();
//                voice_result.setText("播放中...");
//                myPlayer.start();
//
//            } else {
//                myPlayer.pause();
//            }
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

    }

    public static byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while ((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }

    void recognizeRecord() {
        Log.i("haiming","识别");

        AsyncTask<Void,Void,String> loadTask =
                new AsyncTask<Void, Void, String>() {
                    @Override
                    protected String doInBackground(Void... params) {
                        String ret = "";
                        try {
//                            String testpcmfile = "http://www.woyaooo.com/static/test.pcm";
//
//                            HttpURLConnection conn0 = (HttpURLConnection) new URL(testpcmfile).openConnection();
//                            //设置超时间为3秒
//                            conn0.setConnectTimeout(3 * 1000);
//                            //防止屏蔽程序抓取而返回403错误
//                            conn0.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
//
//                            //得到输入流
//                            InputStream inputStream = conn0.getInputStream();
//                            //获取自己数组
//                            byte[] getData = readInputStream(inputStream);
//
//                            //文件保存位置
//
//                            File file = new File(testFileName);
//                            FileOutputStream fos = new FileOutputStream(file);
//                            fos.write(getData);
//                            if (fos != null) {
//                                fos.close();
//                            }
//                            if (inputStream != null) {
//                                inputStream.close();
//                            }
//                            System.out.println("info:" + testpcmfile + " download success");

                            String getTokenURL = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials" +
                                    "&client_id=" + apiKey + "&client_secret=" + secretKey;
                            HttpURLConnection conn = (HttpURLConnection) new URL(getTokenURL).openConnection();
                            token = new JSONObject(printResponse(conn)).getString("access_token");

//                            File pcmFile = new File(testFileName);
                            HttpURLConnection conn2 = (HttpURLConnection) new URL(serverURL
                                    + "?cuid=" + cuid + "&token=" + token).openConnection();

//                            String rootPath = Environment.getExternalStorageDirectory().getPath();
//                            String amrPath = rootPath + "/test.amr";
//                            AmrEncoder.pcm2Amr(testFileName, amrPath);
//                             add request header
                            String rootPath = Environment.getExternalStorageDirectory().getPath();
                            String finalFile = rootPath + "/test.pcm";
                            Common.swapEndian( testFileName,finalFile );
                            conn2.setRequestMethod("POST");
                            conn2.setRequestProperty("Content-Type", "audio/pcm; rate=" + Integer.toString(frequency));

                            conn2.setDoInput(true);
                            conn2.setDoOutput(true);

                            // send request
                            DataOutputStream wr = new DataOutputStream(conn2.getOutputStream());
                            wr.write(loadFile(new File(finalFile)));
                            wr.flush();
                            wr.close();

                            ret = printResponse(conn2) ;

                            Common.uploadFile(  getApplicationContext(),"pcmfileswap.pcm",finalFile);
                            return ret;

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        return null;
                    }
                    @Override
                    protected void onPostExecute(final String response) {

                        voice_result.setText( response);
                    }
                };
        loadTask.execute((Void)null);


    }



    private  void method2() throws Exception {
        File pcmFile = new File(testFileName);
        HttpURLConnection conn = (HttpURLConnection) new URL(serverURL
                + "?cuid=" + cuid + "&token=" + token).openConnection();

        // add request header
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-Type", "audio/pcm; rate=8000");

        conn.setDoInput(true);
        conn.setDoOutput(true);

        // send request
        DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
        wr.write(loadFile(pcmFile));
        wr.flush();
        wr.close();

        voice_result.setText( printResponse(conn) );
    }

    private  String printResponse(HttpURLConnection conn) throws Exception {
        if (conn.getResponseCode() != 200) {
            // request error
            return "";
        }
        InputStream is = conn.getInputStream();
        BufferedReader rd = new BufferedReader(new InputStreamReader(is));
        String line;
        StringBuffer response = new StringBuffer();
        while ((line = rd.readLine()) != null) {
            response.append(line);
            response.append('\r');
        }
        rd.close();
//        voice_result.setText(new JSONObject(response.toString()).toString(4));
        System.out.println(new JSONObject(response.toString()).toString(4));
        return response.toString();
    }

    private  byte[] loadFile(File file) throws IOException {
        InputStream is = new FileInputStream(file);

        long length = file.length();
        byte[] bytes = new byte[(int) length];

        int offset = 0;
        int numRead = 0;
        while (offset < bytes.length
                && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
            offset += numRead;
        }

        if (offset < bytes.length) {
            is.close();
            throw new IOException("Could not completely read file " + file.getName());
        }

        is.close();
        return bytes;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        return false;
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if (keyCode == KeyEvent.KEYCODE_BACK) {
            return false;
        }
        return super.onKeyDown(keyCode, event);
    }

    private class RecordAudio extends AsyncTask<Void, Integer, Void>
    {
        @Override
        protected Void doInBackground(Void... params) {
            isRecording = true;

            Log.i("haiming", "准备就绪，可以开始说话");

            try {
                DataOutputStream dos = new DataOutputStream(
                        new BufferedOutputStream(new FileOutputStream(
                                recordingFile)));

                int bufferSize = AudioTrack.getMinBufferSize(frequency, channelConfiguration, audioEncoding);

                AudioRecord audioRecord = new AudioRecord(audioSource, frequency,
                        channelConfiguration, audioEncoding, bufferSize);
                short[] buffer = new short[bufferSize];
//                int read = audioRecord.read(buffer, 0, bufferSize);
//                if (AudioRecord.ERROR_INVALID_OPERATION == read) {
//                    Common.showSnack(VoiceActivity.this,voice_result,"您拒绝了录音权限，请允许");
//                    return null;
//                }
                audioRecord.startRecording();

                int r = 0;
                while (isRecording)
                {
                    int bufferReadResult = audioRecord.read(buffer, 0,
                            bufferSize);
                    for (int i = 0; i < bufferReadResult; i++)
                    {
                        dos.writeShort(buffer[i]);
                    }

                    publishProgress(new Integer(r));
                    r++;
                }

                audioRecord.stop();
                dos.close();
                Common.uploadFile(  getApplicationContext(),"pcmfile.pcm",testFileName);

            } catch (IOException e) {
                e.printStackTrace();
            }

            return null;
        }

        protected void onProgressUpdate(Integer... progress)
        {
            voice_result.setText(progress[0].toString());
        }

        protected void onPostExecute(Void result)
        {
            startBtn.setEnabled(true);
            stopBtn.setEnabled(false);
            playBtn.setEnabled(true);
        }
    }

    private class PlayAudio extends AsyncTask<Void, Integer, Void>
    {
        @Override
        protected Void doInBackground(Void... params)
        {

            try
            {

                int bufferSize = AudioTrack.getMinBufferSize(frequency,
                        channelConfiguration, audioEncoding);
                short[] audiodata = new short[bufferSize / 4];

                DataInputStream dis = new DataInputStream(
                        new BufferedInputStream(new FileInputStream(
                                recordingFile)));

                AudioTrack audioTrack = new AudioTrack(
                        AudioManager.STREAM_MUSIC, frequency,
                        AudioFormat.CHANNEL_OUT_MONO, audioEncoding, bufferSize,
                        AudioTrack.MODE_STREAM);

                audioTrack.play();

                while (dis.available() > 0)
                {
                    int i = 0;
                    while (dis.available() > 0 && i < audiodata.length)
                    {
                        audiodata[i] = dis.readShort();
                        i++;
                    }
                    audioTrack.write(audiodata, 0, audiodata.length);
                }

                dis.close();

            } catch (Exception e) {
                e.printStackTrace();
                Log.e("haiming", "Playback Failed");
            }



            return null;
        }
    }

    void startASR() {
        Intent intent = new Intent();
        intent.putExtra("outfile", testFileName);
//        bindParams(intent);
        speechRecognizer.startListening(intent);
    }

    public void onReadyForSpeech(Bundle params) {
        Log.i("haiming","准备就绪，可以开始说话");

    }
    @Override
    public void onBeginningOfSpeech() {
        // 开始说话处理
        Log.i("haiming","检测到用户的已经开始说话");
    }

    public void onRmsChanged(float rmsdB) {
        // 音量变化处理
        Log.i("haiming","准备就绪，可以开始说话");
    }

    public void onBufferReceived(byte[] buffer) {
        // 录音数据传出处理
        Log.i("haiming","准备就绪，可以开始说话");
    }

    public void onEndOfSpeech() {
        // 说话结束处理
        Log.i("haiming","检测到用户的已经停止说话");
        Common.uploadFile(  getApplicationContext(),"baidu.pcm",testFileName);
    }

    public void onError(int error) {
        // 出错处理
        StringBuilder sb = new StringBuilder();
        switch (error) {
            case SpeechRecognizer.ERROR_AUDIO:
                sb.append("音频问题");
                break;
            case SpeechRecognizer.ERROR_SPEECH_TIMEOUT:
                sb.append("没有语音输入");
                break;
            case SpeechRecognizer.ERROR_CLIENT:
                sb.append("其它客户端错误");
                break;
            case SpeechRecognizer.ERROR_INSUFFICIENT_PERMISSIONS:
                sb.append("权限不足");
                break;
            case SpeechRecognizer.ERROR_NETWORK:
                sb.append("网络问题");
                break;
            case SpeechRecognizer.ERROR_NO_MATCH:
                sb.append("没有匹配的识别结果");
                break;
            case SpeechRecognizer.ERROR_RECOGNIZER_BUSY:
                sb.append("引擎忙");
                break;
            case SpeechRecognizer.ERROR_SERVER:
                sb.append("服务端错误");
                break;
            case SpeechRecognizer.ERROR_NETWORK_TIMEOUT:
                sb.append("连接超时");
                break;
        }
        sb.append(":" + error);
        startBtn.setText("开始");
        Log.i("haiming",sb.toString());
    }

    public void onResults(Bundle results) {
        ArrayList<String> nbest = results.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
        String content =  Arrays.toString(nbest.toArray(new String[nbest.size()]));
        voice_result.setText(voice_result.getText() + "\n" + content );
//       startASR();
    }

    public void onPartialResults(Bundle partialResults) {
        // 临时结果处理

//        ArrayList<String> nbest = partialResults.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
//        if (nbest.size() > 0) {
//            Log.i("haiming","~临时识别结果：" + Arrays.toString(nbest.toArray(new String[0])));
//            voice_result.setText(nbest.get(0));
//        }
    }

    public void onEvent(int eventType, Bundle params) {
        // 处理事件回调
        Log.i("haiming","准备就绪，可以开始说话");
    }
}
